#!/usr/bin/env python

# make_template

from __future__ import division

import sys
import math
from optparse import OptionParser

from ot_simulator.template.template_funs import frange, mirror
from ot_simulator import graph

def arc(start_angle, inc=1.0, radius=1.0):
    r'''Yields x, y values from -90 - start_angle to the angle the returns to 0.

    x ranges from 0 to 0.25.  y values range from scale to 0 (through -scale).
    '''

    def x_y(angle):
        a_radians = math.radians(angle)
        c, s = math.cos(a_radians), math.sin(a_radians)
        return radius * c, radius * s 

    x_offset, y_offset = x_y(-90 - start_angle)

    end_y = (y_offset - radius) / 2
    end_angle_radians = math.asin(end_y/radius)
    end_angle = math.degrees(end_angle_radians)
    end_x = radius * math.cos(end_angle_radians)
    scale = 0.25 / (end_x - x_offset)

    print "x_offset", x_offset, "y_offset", y_offset, "end_y", end_y, \
          "end_angle", end_angle

    for a in frange(inc, -90 - start_angle, end_angle):
        x, y = x_y(a)
        x_out, y_out = (x - x_offset) * scale, (y - end_y) * scale
        yield x_out, y_out

Template = None

def as_bool(s):
    if s.lower() in ('t', 'true'): return True
    if s.lower() in ('f', 'false'): return True
    raise ValueError("{0} not a boolean value, must be 'true' or 'false'"
                       .format(s))

def push(option, opt, value, parser, fn, value_type, stack = False):
    global Template
    if stack:
        assert Template, "your first argument must not come first!"
        Template = fn(Template,
                      *tuple(value_type(v) for v in value.split(',')))
    else:
        Template = fn(*tuple(value_type(v) for v in value.split(',')))

def to_csv(seq, filename):
    f_close = False
    if filename == 'stdout':
        f = sys.stdout
    elif filename == 'stderr':
        f = sys.stderr
    else:
        f = open(filename, 'wt')
        f_close = True
    try:
        for x, y in seq:
            print >> f, "{0:.4f},{1:.4f}".format(x, y)
    finally:
        if f_close: f.close()

def to_graph(seq):
    g = graph.graph()
    g.plot(seq)
    g.show()

if __name__ == "__main__":
    parser = OptionParser(version= '%prog 0.1.0')

    parser.add_option('-a', "--arc", type="string",
                      action="callback",
                      callback=push,
                      callback_args=(arc, float),
                      help="circular arc from -90 - angle to -90",
                      metavar="ANGLE[,INC[,RADIUS]]",
                     )

    parser.add_option('-m', "--mirror", type="string",
                      action="callback",
                      callback=push,
                      callback_args=(mirror, as_bool, True),
                      help="mirror the prior template",
                      metavar="[DUP_FIRST?[,FLIP_Y]]",
                     )

    parser.add_option('-o', "--output", type="string", default=None,
                      help="output csv file, shown as graph if omitted",
                      metavar="CSV_FILENAME",
                     )

    (options, args) = parser.parse_args()

    if len(args) > 0:
        parser.error("incorrect number of arguments")

    if options.output:
        to_csv(Template, options.output)
    else:
        to_graph(Template)


